package mobileann.mafamily.utils;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import mobileann.mafamily.act.main.FS;
import mobileann.mafamily.db.model.EZoneDBModel;
import mobileann.mafamily.db.model.LocationTrackModel;
import mobileann.mafamily.entity.EleEntity;
import mobileann.mafamily.entity.LocationEntity;
import mobileann.mafamily.entity.LocationTrackBean;
import mobileann.mafamily.entity.MessageBean;
import mobileann.mafamily.model.UDPSocket;
import mobileann.mafamily.service.MainService;
import mobileann.mafamily.utils.MapTag.FSLocListener;
import android.content.Context;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.mapapi.utils.CoordinateConverter.CoordType;
import com.baidu.mapapi.utils.DistanceUtil;
import com.mofind.android.base.L;
import com.mofind.java.utils.TimeUtils;

public class GPSUtils{
	private Context mContext;
	private LocationManager locManager;
	private static GPSUtils _instance = null;
	private Thread thdTimeout = null;
	private CoordinateConverter converter;

	private static final long LOC_TIME = 5000;
	private static final long OUT_TIME_FRIST = 5 * 60 * 1000;
	private static final String OUT_TAG = "OUT_TIME_FRIST";
	private static final int NET_LOC = 1111;
	
	private String fristTag;
	private MyHandler handler = new MyHandler();

	public static synchronized GPSUtils getInstance(Context c) {
		if (_instance == null) {
			_instance = new GPSUtils(c);
		}
		return _instance;
	}

	private GPSUtils(Context c) {
		this.mContext = c;
		locManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
	}
	// 绑定监听，有4个参数
	// 参数1，设备：有GPS_PROVIDER和NETWORK_PROVIDER两种
	// 参数2，位置信息更新周期，单位毫秒
	// 参数3，位置变化最小距离：当位置距离变化超过此值时，将更新位置信息
	// 参数4，监听
	// 备注：参数2和3，如果参数3不为0，则以参数3为准；参数3为0，则通过时间来定时更新；两者为0，则随时刷新
	// 1秒更新一次，或最小位移变化超过1米更新一次；
	// 注意：此处更新准确度非常低，推荐在service里面启动一个Thread，在run中sleep(10000);然后执行handler.sendMessage(),更新位置
	//	locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 100, locationListener);

//	public void startGPS(){
//		if(locManager == null){
//			locManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
//		}
//		locManager.addGpsStatusListener(gpsStatusListener);
//		locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, locationListener);
//	}

	public void startGPSSingle(){
		if(locManager == null){
			locManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
		}
		locManager.addGpsStatusListener(gpsStatusListener);
		locManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListener, null);
	}

	public void onDestory(){
		if(locManager != null){
			locManager.removeUpdates(locationListener);
			locManager.removeGpsStatusListener(gpsStatusListener);
			locManager = null;
		}
	}
	
	private void setTimeOut(final long outtime){
		cancelTimeOut();
		thdTimeout = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					Thread.sleep(outtime);
					if(NetUtils.getInstance().netstate() != 0)
						handler.obtainMessage(NET_LOC).sendToTarget();
					if(OUT_TAG.equals(fristTag)){
						SPUtils.setFristRecordSucceed(false);
						fristTag = "";
					}
//					L.i("LocationMode", "超时，GPS定位结束");
//					SPUtils.setGPSWork(false);
					FS.gpsWroking = false;
					onDestory();
				} catch (InterruptedException e) {
					L.e("maf", "error--", e);
				}
			}
		});
		thdTimeout.start();
	}

	private void cancelTimeOut(){
		if (thdTimeout != null) {
			thdTimeout.interrupt();
			try {
				thdTimeout.join(3600);
			} catch (InterruptedException e) {
				L.e("maf", "error--", e);
			}
			thdTimeout = null;
		}
	}

	/**
	 *  主要功能:
	 *  <br>位置监听
	 *  <br>
	 *  @annotation ADRIAN.2015.8.10.12.02
	 */
	LocationListener locationListener = new LocationListener() {

		/** 
		 * 位置信息变化时触发 
		 */
		public void onLocationChanged(Location location) {
			if(location != null){
				converter  = new CoordinateConverter();
				converter.from(CoordType.GPS);
				// sourceLatLng待转换坐标
				LatLng sourceLatLng =
						new LatLng(location.getLatitude(),location.getLongitude());
				converter.coord(sourceLatLng);
				LatLng desLatLng = converter.convert();
				int theX = (int)(desLatLng.latitude * 1e6);
				int theY = (int)(desLatLng.longitude * 1e6);
				MainService.iCurrLatitude = theX;
				MainService.iCurrLongitude = theY;
				MainService.iCurrLocType = LocationUtis.GPS_LOCATE/*2*/;
				LocationEntity loc = new LocationEntity(SPUtils.getUID(),
						SPUtils.getFID(),
						desLatLng.longitude,
						desLatLng.latitude,
						String.valueOf(TimeUtils.getDateTimeStr(System.currentTimeMillis())),
						"未知位置",
						String.valueOf(LocationUtis.GPS_LOCATE));
				 if (fsLocListener != null) {
					 fsLocListener.onReceiveLocation(loc);
                 }
				 // 如果没有网络,记录到本地
				 if(NetUtils.getInstance().netstate() == 0){ // 离线状态
					 //保存坐标信息到本地
					 LocationTrackBean locBean = new LocationTrackBean(SPUtils.getFID()
							 , SPUtils.getUID()
							 , theY
							 , theX
							 , String.valueOf(TimeUtils.getDateTimeStr(location.getTime()))
							 , String.valueOf(LocationUtis.GPS_LOCATE));
					 LocationTrackModel.insertTrackInfo(locBean, mContext);
//					 L.i("LocationMode", "保存坐标信息到本地"+"GPS :"+theX + " :: " + theY);
				 }else{ // 如果有网络,则直接上传到服务器
					 UDPSocket.getInstance(mContext).sendLocationRequest(String.valueOf(theX),
							 String.valueOf(theY),
							 "no address",
							 String.valueOf(LocationUtis.GPS_LOCATE)/*"2"*/);
					 SetELENAME(theX, theY);
				 }
			}
		}

		/** 
		 * GPS状态变化时触发 
		 */
		public void onStatusChanged(String provider, int status, Bundle extras) {
			switch (status) {
				// GPS状态为可见时
			case LocationProvider.AVAILABLE:
				break;
				// GPS状态为暂停服务时
			case LocationProvider.TEMPORARILY_UNAVAILABLE:
				break;
				// GPS状态为服务区外时
			case LocationProvider.OUT_OF_SERVICE:
				break;
			}
		}

		/** 
		 * GPS开启时触发 
		 */
		public void onProviderEnabled(String provider) {
		}

		/** 
		 * GPS禁用时触发 
		 */
		public void onProviderDisabled(String provider) {
//			SPUtils.setGPSWork(false);
			FS.gpsWroking = false;
			onDestory();
		}
	};

	// 状态监听
	GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
		public void onGpsStatusChanged(int event) {
			switch (event) {
			// 卫星状态改变
			case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
//				// 获取当前状态
//				GpsStatus gpsStatus = locManager.getGpsStatus(null);
//				// 创建一个迭代器保存所有卫星
//				Iterator<GpsSatellite> iters =
//						gpsStatus.getSatellites().iterator();
//				// 获取卫星颗数的默认最大值
//				int maxSatellites = gpsStatus.getMaxSatellites();
//				int count = 0;
//				while (iters.hasNext() && count <= maxSatellites) {
//					iters.next();
//					count++;
//				}
//				L.i("LocationMode", "sates:"+count);
				break;
				// 第一次定位成功
			case GpsStatus.GPS_EVENT_FIRST_FIX:
				cancelTimeOut();
//				SPUtils.setGPSWork(false);
				FS.gpsWroking = false;
				SPUtils.setGPSRecord(true);
				SPUtils.setFristRecordSucceed(true);
				SPUtils.setLocTypeCount(0);
//				L.i("LocationMode", "第一次定位成功");
				break;
				// 定位启动
			case GpsStatus.GPS_EVENT_STARTED:
//				SPUtils.setGPSWork(true);
				FS.gpsWroking = true;
				if(SPUtils.getGPSRecord()){
					setTimeOut(LOC_TIME);
					fristTag = "";
				}else{
					if(NetUtils.getInstance().hasWifi()){
						setTimeOut(OUT_TIME_FRIST);
						fristTag = OUT_TAG;
					}
					if(NetUtils.getInstance().netstate() != 0)
						handler.obtainMessage(NET_LOC).sendToTarget();
				}
//				L.i("LocationMode", "定位启动");
				break;
				// 定位结束
			case GpsStatus.GPS_EVENT_STOPPED:
//				SPUtils.setGPSWork(false);
				FS.gpsWroking = false;
//				L.i("LocationMode", "定位结束");
				break;
			}
		};
	};
	
	public boolean GPSOpen(){
		if(locManager == null){
			locManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
		}
		if(MySelfUtils.getInstance().hasAuthority(mContext, "android.permission.ACCESS_FINE_LOCATION")){
			if(!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
				return false;
			}else{
				return true;
			}
		}else{
			return false;
		}
	}

	private FSLocListener fsLocListener;
	public void setLocationListener(FSLocListener fsLocListener) {
		this.fsLocListener = fsLocListener;
	}
	
	private double getdistance(int i, int i2, int j, int j2) {
		LatLng p1LL = new LatLng((double) i / 1e6, (double) i2 / 1e6);
		LatLng p2LL = new LatLng((double) j / 1e6, (double) j2 / 1e6);
		double distance = DistanceUtil.getDistance(p1LL, p2LL);
		return distance;
	}
	
	/**
	 * 查看本人是否处于某个围栏
	 * 
	 * @param x
	 *            当前坐标x
	 * @param y
	 *            当前坐标y
	 * @return 围栏名称（没有则为空）
	 */
	private String CheckELE(int x, int y) {
		String point2 = "";
		List<EleEntity> elelist2 = EZoneDBModel.queryAll(FS.getInstance());
		if (elelist2 != null && elelist2.size() > 0) {
			for (int i = 0; i < elelist2.size(); i++) {
				int c1 = Integer.valueOf(elelist2.get(i).getLatitude());
				int c2 = Integer.valueOf(elelist2.get(i).getLongitude());
				double distance = getdistance(x, y, c1, c2);
				double radius = Double.valueOf(elelist2.get(i).getRadius());
				if (distance <= radius) {
					point2 = (String) elelist2.get(i).getDesc();
					return point2;
				}
			}
		}
		return point2;
	}
	
	/**
	 * 记录当前所处围栏名称，并在符合条件时发送系统消息
	 * 
	 * @param x
	 *            坐标x
	 * @param y
	 *            坐标y
	 */
	private void SetELENAME(int x, int y) {
		String sr = CheckELE(x, y);
		String elename = SPUtils.getELENAME();
		if (sr.equals(elename)) {
		} else {
			SimpleDateFormat formatter = new SimpleDateFormat("MM月dd日 HH:mm:ss");
			if (sr.equals("")) {
				MessageBean msg = new MessageBean();
				msg.setFid(SPUtils.getFID());
				msg.setUid(SPUtils.getUID());
				msg.setSort(MessageBean.SYSTEM);
				msg.setTime(formatter.format(new Date()));
				msg.setText("已离开 < " + elename + " > ");
				UDPSocket.getInstance(FS.getInstance()).Send_Message_toServer(
						msg);
				SPUtils.setELENAME(sr);
			} else if (elename.equals("")) {
				MessageBean msg = new MessageBean();
				msg.setFid(SPUtils.getFID());
				msg.setUid(SPUtils.getUID());
				msg.setSort(MessageBean.SYSTEM);
				msg.setTime(formatter.format(new Date()));
				msg.setText("已到 < " + sr + " > ");
				UDPSocket.getInstance(FS.getInstance()).Send_Message_toServer(
						msg);
				SPUtils.setELENAME(sr);
			} else {
				MessageBean msg = new MessageBean();
				msg.setFid(SPUtils.getFID());
				msg.setUid(SPUtils.getUID());
				msg.setSort(MessageBean.SYSTEM);
				msg.setTime(formatter.format(new Date()));
				msg.setText("已离开 < " + elename + " > ，同时已到 < " + sr
						+ " > ");
				UDPSocket.getInstance(FS.getInstance()).Send_Message_toServer(
						msg);
				SPUtils.setELENAME(sr);
			}
		}
	}
	
	private static class MyHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case NET_LOC:
				BaiduLocationUtils
					.getInstance(FS.getInstance()).requestLocation();
				break;
			default:
				break;
			}
		}
	}
}
